package com.hd.hdxgddcommon.controller;

import com.hd.hdxgddcommon.constant.ResultConst;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * <p>
 * 自定义异常处理 控制器
 * </p>
 *
 * @author Administrator
 * @since 2019-01-15
 */
@Controller
@RequestMapping("/error")
public class ErrorResolveController extends BasicErrorController {

    @Autowired
    public ErrorResolveController(ErrorAttributes errorAttributes,
                                  ErrorProperties errorProperties) {
        super(errorAttributes, errorProperties);
    }

    @Override
    public String getErrorPath() {
        return "error";
    }

    /**
     * 处理请求头的"Accept"属性包含"text/html"的http请求
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(produces = "text/html")
    public ModelAndView errorHtml(HttpServletRequest request,
                                  HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        String errorPage = this.getErrorPage(status);
        ModelAndView modelAndView = new ModelAndView(errorPage);
        modelAndView.setStatus(HttpStatus.OK);
        return modelAndView;
    }

    /**
     * 处理默认的http请求
     *
     * @param request
     * @return
     */
    @RequestMapping
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> errorAttributes = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = this.getStatus(request);
        Map<String, Object> result = null;
        ResultConst resultConst = this.getResultConst(status);
        if (resultConst == null) {
            resultConst = ResultConst.UNKNOWN_EXCEPTION;
        }
        //处理发生的异常信息
        List errors = (List) errorAttributes.get("errors");
        if (errors != null && !errors.isEmpty()) {
            Object error = errors.get(0);
            if (error instanceof MessageSourceResolvable) {
                MessageSourceResolvable resolvable = (MessageSourceResolvable) error;
                result = this.getResultMap(resultConst.getCode(), resolvable.getDefaultMessage());
            } else if (error instanceof Throwable) {
                Throwable throwable = (Throwable) error;
                result = this.getResultMap(resultConst.getCode(), throwable.getMessage());
            }
        }
        if (result == null) {
            result = this.getResultMap(resultConst.getCode(), resultConst.getMsg());
        }
        return new ResponseEntity(result, HttpStatus.OK);
    }

    public ResultConst getResultConst(HttpStatus status) {
        if (status == null) return ResultConst.UNKNOWN_EXCEPTION;
        int statusCode = status.value();
        ResultConst resultConst;
        switch (statusCode) {
            case 400:
                resultConst = ResultConst.ILLEGAL_PARAM;
                break;
            case 404:
                resultConst = ResultConst.INVALID_PATH;
                break;
            case 500:
                resultConst = ResultConst.SERVICE_EXCEPTION;
                break;
            default:
                resultConst = ResultConst.FAIL;
        }
        return resultConst;
    }

    public String getErrorPage(HttpStatus status) {
        if (status == null) return "error404";
        int statusCode = status.value();
        String errorPage;
        switch (statusCode) {
            case 400:
                errorPage = "error400";
                break;
            case 500:
                errorPage = "error500";
                break;
            default:
                //其他异常返回普通失败 , 错误页面对应404错误
                errorPage = "error404";
        }
        return errorPage;
    }

    public Map<String, Object> getResultMap(int code, String msg) {
        Map<String, Object> result = new HashMap<>();
        result.put("code", code);
        result.put("msg", msg);
        return result;
    }
}
